#include "HeightRecordModel.h"
#include <QSettings>
#include <QStandardPaths>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QVariantMap>
#include <QFile>
#include <QDir>
#include <QDebug>
#include <QCryptographicHash>
#include <algorithm>

HeightRecordModel::HeightRecordModel(QObject *parent)
    : QAbstractListModel(parent)
    , m_networkManager(new QNetworkAccessManager(this))
    , m_dataModified(false)
{
    loadData();
}

int HeightRecordModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return m_records.size();
}

QVariant HeightRecordModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() >= m_records.size())
        return QVariant();

    const HeightRecord& record = m_records[index.row()];

    switch (role) {
    case DateRole:
        return record.date;
    case HeightRole:
        return record.height;
    case DateStringRole:
        return record.date.toString("yyyy-MM-dd");
    case YearRole:
        return record.date.year();
    case MonthRole:
        return record.date.month();
    case DayRole:
        return record.date.day();
    default:
        return QVariant();
    }
}

QHash<int, QByteArray> HeightRecordModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[DateRole] = "recordDate";
    roles[HeightRole] = "height";
    roles[DateStringRole] = "dateString";
    roles[YearRole] = "year";
    roles[MonthRole] = "month";
    roles[DayRole] = "day";
    return roles;
}

double HeightRecordModel::currentHeight() const
{
    if (m_records.isEmpty())
        return 0.0;
    return m_records.last().height;
}

double HeightRecordModel::lastYearGrowth() const
{
    if (m_records.size() < 2)
        return 0.0;

    // 获取最新记录
    double currentHeight = m_records.last().height;
    QDate latestDate = m_records.last().date;
    QDate oneYearAgo = latestDate.addYears(-1);

    // 查找一年前最接近的记录
    double pastHeight = 0.0;
    bool foundPastRecord = false;

    // 从后往前查找（因为已排序）
    for (int i = m_records.size() - 2; i >= 0; --i) {
        if (m_records[i].date <= oneYearAgo) {
            pastHeight = m_records[i].height;
            foundPastRecord = true;
            break;
        }
    }

    // 如果没找到一年前的记录（数据不足一年），使用最早的记录
    if (!foundPastRecord) {
        pastHeight = m_records.first().height;
    }

    return currentHeight - pastHeight;
}

QVariantList HeightRecordModel::getChartData() const
{
    QVariantList result;
    for (const HeightRecord& record : m_records) {
        QVariantMap item;
        item["date"] = record.date.toString("yyyy-MM-dd");
        item["height"] = record.height;
        result.append(item);
    }
    return result;
}

void HeightRecordModel::addRecord(const QDate& date, double height)
{
    if (!date.isValid() || height <= 0)
        return;

    // 检查是否已有相同日期的记录
    for (int i = 0; i < m_records.size(); ++i) {
        if (m_records[i].date == date) {
            // 更新现有记录
            m_records[i].height = height;
            sortRecords();
            
            // 找到排序后的位置并发出信号
            for (int j = 0; j < m_records.size(); ++j) {
                if (m_records[j].date == date) {
                    QModelIndex idx = index(j, 0);
                    emit dataChanged(idx, idx);
                    break;
                }
            }
            
            saveData();
            emit currentHeightChanged();
            emit lastYearGrowthChanged();
            m_dataModified = true;  // 标记数据已修改
            return;
        }
    }

    // 添加新记录
    beginInsertRows(QModelIndex(), m_records.size(), m_records.size());
    m_records.append(HeightRecord(date, height));
    endInsertRows();

    sortRecords();
    saveData();

    emit countChanged();
    emit currentHeightChanged();
    emit lastYearGrowthChanged();
    m_dataModified = true;  // 标记数据已修改
}

void HeightRecordModel::addRecord(const QString& dateString, double height)
{
    QDate date = QDate::fromString(dateString, "yyyy-MM-dd");
    if (!date.isValid()) {
        date = QDate::currentDate();
    }
    addRecord(date, height);
}

void HeightRecordModel::deleteRecord(int index)
{
    if (index < 0 || index >= m_records.size())
        return;

    beginRemoveRows(QModelIndex(), index, index);
    m_records.removeAt(index);
    endRemoveRows();

    saveData();

    emit countChanged();
    emit currentHeightChanged();
    emit lastYearGrowthChanged();
    m_dataModified = true;  // 标记数据已修改
}

QString HeightRecordModel::getYearlyGrowthDetails() const
{
    if (m_records.size() < 2)
        return "暂无足够数据";

    // 按年份分组统计
    QMap<int, QPair<double, double>> yearlyData; // year -> (minHeight, maxHeight)

    for (const HeightRecord& record : m_records) {
        int year = record.date.year();
        if (!yearlyData.contains(year)) {
            yearlyData[year] = qMakePair(record.height, record.height);
        } else {
            yearlyData[year].first = qMin(yearlyData[year].first, record.height);
            yearlyData[year].second = qMax(yearlyData[year].second, record.height);
        }
    }

    // 构建详情字符串
    QString details;
    QList<int> years = yearlyData.keys();
    std::sort(years.begin(), years.end());

    for (int i = 0; i < years.size(); ++i) {
        int year = years[i];
        double minHeight = yearlyData[year].first;
        double maxHeight = yearlyData[year].second;
        double growth = maxHeight - minHeight;

        details += QString("%1年：").arg(year);
        
        if (growth > 0.1) {
            details += QString("%1 cm → %2 cm，生长 %3 cm\n")
                          .arg(minHeight, 0, 'f', 1)
                          .arg(maxHeight, 0, 'f', 1)
                          .arg(growth, 0, 'f', 1);
        } else {
            details += QString("%1 cm（单次记录）\n").arg(minHeight, 0, 'f', 1);
        }
    }

    // 计算年均生长速度
    if (years.size() >= 2) {
        int firstYear = years.first();
        int lastYear = years.last();
        double firstHeight = yearlyData[firstYear].first;
        double lastHeight = yearlyData[lastYear].second;
        double totalGrowth = lastHeight - firstHeight;
        int yearSpan = lastYear - firstYear;
        
        if (yearSpan > 0) {
            double avgGrowthPerYear = totalGrowth / yearSpan;
            details += QString("\n📊 %1-%2年平均每年生长：%3 cm")
                          .arg(firstYear).arg(lastYear).arg(avgGrowthPerYear, 0, 'f', 1);
        }
    }

    return details.trimmed();
}

double HeightRecordModel::getGrowthBetweenDates(const QDate& startDate, const QDate& endDate) const
{
    if (m_records.size() < 2)
        return 0.0;

    double startHeight = 0.0;
    double endHeight = 0.0;
    bool foundStart = false;
    bool foundEnd = false;

    // 查找起始和结束日期最接近的记录
    for (const HeightRecord& record : m_records) {
        if (!foundStart && record.date >= startDate) {
            startHeight = record.height;
            foundStart = true;
        }
        if (record.date <= endDate) {
            endHeight = record.height;
            foundEnd = true;
        }
    }

    if (foundStart && foundEnd) {
        return endHeight - startHeight;
    }

    return 0.0;
}

void HeightRecordModel::loadData()
{
    QString dataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    QDir().mkpath(dataPath);  // 确保目录存在
    QString filePath = dataPath + "/height_records.json";
    
    QFile file(filePath);
    if (!file.exists()) {
        qDebug() << "身高记录文件不存在，将创建新文件:" << filePath;
        return;
    }
    
    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "无法打开身高记录文件:" << filePath;
        return;
    }

    QByteArray data = file.readAll();
    file.close();
    
    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (!doc.isArray()) {
        qWarning() << "身高记录文件格式错误";
        return;
    }

    QJsonArray array = doc.array();
    m_records.clear();
    
    for (const QJsonValue& value : array) {
        if (!value.isObject())
            continue;

        QJsonObject obj = value.toObject();
        QString dateStr = obj["date"].toString();
        double height = obj["height"].toDouble();

        QDate date = QDate::fromString(dateStr, "yyyy-MM-dd");
        if (date.isValid() && height > 0) {
            m_records.append(HeightRecord(date, height));
        }
    }

    sortRecords();
    qDebug() << "成功加载" << m_records.size() << "条身高记录";
}

void HeightRecordModel::saveData()
{
    QJsonArray array;
    for (const HeightRecord& record : m_records) {
        QJsonObject obj;
        obj["date"] = record.date.toString("yyyy-MM-dd");
        obj["height"] = record.height;
        array.append(obj);
    }

    QJsonDocument doc(array);
    
    QString dataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    QDir().mkpath(dataPath);
    QString filePath = dataPath + "/height_records.json";
    
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly)) {
        qWarning() << "无法写入身高记录文件:" << filePath;
        return;
    }
    
    file.write(doc.toJson(QJsonDocument::Indented));
    file.close();
    
    qDebug() << "成功保存" << m_records.size() << "条身高记录到:" << filePath;
}

void HeightRecordModel::sortRecords()
{
    beginResetModel();
    std::sort(m_records.begin(), m_records.end());
    endResetModel();
}

// ==================== 云同步功能实现 ====================

void HeightRecordModel::setCloudSyncConfig(const QString& owner, const QString& repo, const QString& token)
{
    m_giteeOwner = owner.trimmed();
    m_giteeRepo = repo.trimmed();
    m_giteeToken = token.trimmed();
    
    qDebug() << "身高记录云同步配置已更新:" << m_giteeOwner << "/" << m_giteeRepo;
}

bool HeightRecordModel::isCloudSyncConfigured() const
{
    return !m_giteeOwner.isEmpty() && !m_giteeRepo.isEmpty() && !m_giteeToken.isEmpty();
}

QString HeightRecordModel::getCloudApiUrl() const
{
    return QString("https://gitee.com/api/v5/repos/%1/%2/contents/height_records.json")
        .arg(m_giteeOwner)
        .arg(m_giteeRepo);
}

void HeightRecordModel::syncFromCloud()
{
    if (!isCloudSyncConfigured()) {
        emit syncFailed("云同步未配置");
        return;
    }
    
    emit syncStarted();
    qDebug() << "开始从云端下载身高记录数据...";
    
    QString url = getCloudApiUrl() + "?access_token=" + m_giteeToken;
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    
    QNetworkReply* reply = m_networkManager->get(request);
    
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        reply->deleteLater();
        
        if (reply->error() != QNetworkReply::NoError) {
            QString errorMsg = QString("下载失败: %1").arg(reply->errorString());
            qWarning() << errorMsg;
            emit syncFailed(errorMsg);
            return;
        }
        
        QByteArray responseData = reply->readAll();
        QJsonDocument responseDoc = QJsonDocument::fromJson(responseData);
        
        if (!responseDoc.isObject()) {
            emit syncFailed("云端数据格式错误");
            return;
        }
        
        QJsonObject responseObj = responseDoc.object();
        m_currentFileSha = responseObj["sha"].toString();
        
        QString contentBase64 = responseObj["content"].toString();
        QByteArray decodedData = QByteArray::fromBase64(contentBase64.toUtf8());
        
        QJsonDocument dataDoc = QJsonDocument::fromJson(decodedData);
        if (!dataDoc.isArray()) {
            emit syncFailed("云端身高记录数据格式错误");
            return;
        }
        
        beginResetModel();
        m_records.clear();
        
        QJsonArray array = dataDoc.array();
        for (const QJsonValue& value : array) {
            if (!value.isObject())
                continue;
            
            QJsonObject obj = value.toObject();
            QString dateStr = obj["date"].toString();
            double height = obj["height"].toDouble();
            
            QDate date = QDate::fromString(dateStr, "yyyy-MM-dd");
            if (date.isValid() && height > 0) {
                m_records.append(HeightRecord(date, height));
            }
        }
        
        sortRecords();
        endResetModel();
        
        saveData();  // 保存到本地
        
        emit countChanged();
        emit currentHeightChanged();
        emit lastYearGrowthChanged();
        emit syncFinished();
        
        // 从云端下载后，清除修改标志（因为本地数据已被云端数据覆盖）
        m_dataModified = false;
        
        qDebug() << "成功从云端下载" << m_records.size() << "条身高记录";
    });
}

void HeightRecordModel::syncToCloud()
{
    if (!isCloudSyncConfigured()) {
        emit syncFailed("云同步未配置");
        return;
    }
    
    emit syncStarted();
    qDebug() << "开始上传身高记录到云端...";
    
    // 构建JSON数据
    QJsonArray array;
    for (const HeightRecord& record : m_records) {
        QJsonObject obj;
        obj["date"] = record.date.toString("yyyy-MM-dd");
        obj["height"] = record.height;
        array.append(obj);
    }
    
    QJsonDocument doc(array);
    QByteArray jsonData = doc.toJson(QJsonDocument::Indented);
    QString contentBase64 = jsonData.toBase64();
    
    // 构建Gitee API请求
    QJsonObject requestObj;
    requestObj["access_token"] = m_giteeToken;
    requestObj["content"] = contentBase64;
    requestObj["message"] = "Update height records from app";
    
    if (!m_currentFileSha.isEmpty()) {
        requestObj["sha"] = m_currentFileSha;
    }
    
    QJsonDocument requestDoc(requestObj);
    QByteArray requestData = requestDoc.toJson();
    
    QString url = getCloudApiUrl();
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    
    QNetworkReply* reply = m_networkManager->put(request, requestData);
    
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        reply->deleteLater();
        
        if (reply->error() != QNetworkReply::NoError) {
            QString errorMsg = QString("上传失败: %1").arg(reply->errorString());
            qWarning() << errorMsg;
            emit syncFailed(errorMsg);
            return;
        }
        
        QByteArray responseData = reply->readAll();
        QJsonDocument responseDoc = QJsonDocument::fromJson(responseData);
        
        if (responseDoc.isObject()) {
            QJsonObject responseObj = responseDoc.object();
            if (responseObj.contains("content")) {
                m_currentFileSha = responseObj["content"].toObject()["sha"].toString();
                qDebug() << "上传成功，新SHA:" << m_currentFileSha;
            }
        }
        
        emit syncFinished();
        qDebug() << "成功上传" << m_records.size() << "条身高记录到云端";
        m_dataModified = false;  // 上传成功后重置修改标记
        clearModifiedFlag();  // 确保清除修改标志
    });
}

// 计算数据哈希
QString HeightRecordModel::calculateDataHash() const
{
    // 构建JSON数据
    QJsonArray array;
    for (const HeightRecord& record : m_records) {
        QJsonObject obj;
        obj["date"] = record.date.toString("yyyy-MM-dd");
        obj["height"] = record.height;
        array.append(obj);
    }
    
    QJsonDocument doc(array);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact);
    
    // 计算SHA256哈希
    QByteArray hash = QCryptographicHash::hash(jsonData, QCryptographicHash::Sha256);
    return QString(hash.toHex());
}

// 启动时检查云端数据
void HeightRecordModel::checkAndSyncOnStartup()
{
    if (!isCloudSyncConfigured()) {
        qDebug() << "身高记录云同步未配置，跳过启动检查";
        return;
    }
    
    qDebug() << "启动时检查云端身高记录数据...";
    
    QString url = getCloudApiUrl() + "?access_token=" + m_giteeToken;
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    
    QNetworkReply* reply = m_networkManager->get(request);
    
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        reply->deleteLater();
        
        if (reply->error() != QNetworkReply::NoError) {
            int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
            if (statusCode == 404) {
                qDebug() << "云端身高记录文件不存在";
            } else {
                qDebug() << "检查云端数据失败:" << reply->errorString();
            }
            return;
        }
        
        QByteArray responseData = reply->readAll();
        QJsonDocument responseDoc = QJsonDocument::fromJson(responseData);
        
        if (!responseDoc.isObject()) {
            qDebug() << "云端数据格式错误";
            return;
        }
        
        QJsonObject responseObj = responseDoc.object();
        m_currentFileSha = responseObj["sha"].toString();
        
        QString contentBase64 = responseObj["content"].toString();
        QByteArray decodedData = QByteArray::fromBase64(contentBase64.toUtf8());
        
        QJsonDocument dataDoc = QJsonDocument::fromJson(decodedData);
        if (!dataDoc.isArray()) {
            qDebug() << "云端身高记录数据格式错误";
            return;
        }
        
        // 计算云端数据哈希
        QString cloudHash = QString(QCryptographicHash::hash(
            dataDoc.toJson(QJsonDocument::Compact), 
            QCryptographicHash::Sha256).toHex());
        
        // 计算本地数据哈希
        QString localHash = calculateDataHash();
        
        qDebug() << "云端哈希:" << cloudHash.left(16) << "...";
        qDebug() << "本地哈希:" << localHash.left(16) << "...";
        
        // 对比哈希值
        if (cloudHash != localHash) {
            qDebug() << "检测到云端身高记录数据不同，发送信号";
            emit cloudDataDifferent(cloudHash, localHash);
        } else {
            qDebug() << "云端和本地身高记录数据一致";
        }
    });
}

// 退出时检查本地数据
void HeightRecordModel::checkAndSyncOnExit()
{
    qDebug() << "========== 身高记录退出检查被调用 ==========";
    
    if (!isCloudSyncConfigured()) {
        qDebug() << "身高记录云同步未配置，跳过退出检查";
        return;
    }
    
    if (!m_dataModified) {
        qDebug() << "身高记录数据未修改，跳过退出检查";
        emit dataConsistent();
        return;
    }
    
    qDebug() << "退出时检查身高记录本地数据，开始网络请求...";
    
    QString url = getCloudApiUrl() + "?access_token=" + m_giteeToken;
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    
    QNetworkReply* reply = m_networkManager->get(request);
    
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        reply->deleteLater();
        
        if (reply->error() != QNetworkReply::NoError) {
            int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
            if (statusCode == 404) {
                qDebug() << "云端身高记录文件不存在，提示用户上传";
                emit localDataDifferent("local_exists", "cloud_not_exists");
            } else {
                qDebug() << "检查云端数据失败:" << reply->errorString();
            }
            return;
        }
        
        QByteArray responseData = reply->readAll();
        QJsonDocument responseDoc = QJsonDocument::fromJson(responseData);
        
        if (!responseDoc.isObject()) {
            qDebug() << "云端数据格式错误";
            return;
        }
        
        QJsonObject responseObj = responseDoc.object();
        m_currentFileSha = responseObj["sha"].toString();
        
        QString contentBase64 = responseObj["content"].toString();
        QByteArray decodedData = QByteArray::fromBase64(contentBase64.toUtf8());
        
        QJsonDocument dataDoc = QJsonDocument::fromJson(decodedData);
        if (!dataDoc.isArray()) {
            qDebug() << "云端身高记录数据格式错误";
            return;
        }
        
        // 计算云端数据哈希
        QString cloudHash = QString(QCryptographicHash::hash(
            dataDoc.toJson(QJsonDocument::Compact), 
            QCryptographicHash::Sha256).toHex());
        
        // 计算本地数据哈希
        QString localHash = calculateDataHash();
        
        qDebug() << "云端哈希:" << cloudHash.left(16) << "...";
        qDebug() << "本地哈希:" << localHash.left(16) << "...";
        
        // 对比哈希值
        if (localHash != cloudHash) {
            qDebug() << "检测到本地身高记录数据不同，发送信号";
            emit localDataDifferent(localHash, cloudHash);
        } else {
            qDebug() << "本地和云端身高记录数据一致，发送一致信号";
            emit dataConsistent();
        }
    });
}

// 检查数据是否已修改
bool HeightRecordModel::hasDataModified() const
{
    return m_dataModified;
}

// 清除修改标志
void HeightRecordModel::clearModifiedFlag()
{
    m_dataModified = false;
    qDebug() << "✅ 身高记录修改标志已清除";
}

